package tt.dz.biz.service.rpc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.math.BigDecimal;
import java.util.List;
import javax.annotation.Resource;
import org.apache.avro.Protocol;
import org.apache.avro.Protocol.Message;
import org.apache.avro.generic.GenericRecord;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import tt.dz.biz.dao.financial.MerchantDAO;
import tt.dz.biz.dao.order.OrderServiceDAOImpl;
import tt.dz.biz.dao.trade.TradeDAOImpl;
import tt.dz.biz.service.card.CardTypeServiceImpl;
import tt.dz.biz.service.common.CommonService;
import tt.dz.biz.service.user.OfflineAccountService;
import tt.dz.common.BigDecimalUtil;
import tt.dz.common.BusinessException;
import tt.dz.common.DZStringUtil;
import tt.dz.common.DateUtil;
import tt.dz.common.DzConstants;
import tt.dz.common.DzConstants.CardType;
import tt.dz.common.DzConstants.PayType;
import tt.dz.common.DzConstants.accountingState;
import tt.dz.common.DzConstants.cardState;
import tt.dz.common.DzConstants.payState;
import tt.dz.common.DzConstants.userType;
import tt.dz.common.DzErrorCode;
import tt.dz.common.DzErrorCode.CardErrorCode;
import tt.dz.common.DzErrorCode.CommonErrorCode;
import tt.dz.common.DzErrorCode.ExceptionErrorCode;
import tt.dz.common.DzErrorCode.MerchErrorCode;
import tt.dz.common.DzErrorCode.TranErrorCode;
import tt.dz.common.LogUtil;
import tt.dz.vo.MerchantVO;
import tt.dz.vo.OfflineAccountVO;
import tt.dz.vo.OrderServiceVO;
import tt.dz.vo.TranInfoVO;

@Service("rpcOfflineCardService")
public class RPCOfflineCardService
  implements RPCBaseService
{
  @Resource(name="offlineAccountService")
  OfflineAccountService offlineAccountService;
  @Resource(name="orderServiceDAO")
  private OrderServiceDAOImpl orderService;
  @Resource(name="commonService")
  private CommonService commonService;
  @Resource(name="cardTypeServiceImpl")
  private CardTypeServiceImpl cardTypeServiceImpl;
  @Resource(name="tradeDAO")
  private TradeDAOImpl tradeDAO;
  @Resource(name="merchantDAO")
  private MerchantDAO merchantDAO;
  @Value("${recharge.service.no}")
  private String rechargeServiceNo;
  @Value("${cancelOfflineCard.service.no}")
  private String cancelOfflineCardServiceNo;
  
  public Object execute(Protocol.Message message, Object request, Protocol protocol)
    throws Exception
  {
    Object req = ((GenericRecord)request).get("req");
    JSONObject reqObj = JSON.parseObject(req.toString());
    String cardNo = reqObj.getString("cardNo");
    String cardType = this.cardTypeServiceImpl.getCardType(cardNo);
    if (!DzConstants.CardType.OFFLINE_CARD.value().equals(cardType)) {
      throw new BusinessException(DzErrorCode.CardErrorCode.CARD_TYPE_ERROR.value(), DzErrorCode.CardErrorCode.CARD_TYPE_ERROR.getDesc(), DzErrorCode.CardErrorCode.CARD_TYPE_ERROR.getDesc());
    }
    String methodName = message.getName();
    if ("activateOfflineCard".equals(methodName)) {
      return activateCard(request);
    }
    if ("queryOfflineCard".equals(methodName)) {
      return queryOfflineCard(request);
    }
    if ("rechargeOfflineAccount".equals(methodName)) {
      return recharge(request);
    }
    if ("cancelOfflineCard".equals(methodName)) {
      return cancelOfflineCard(request);
    }
    return "";
  }
  
  private Object activateCard(Object request)
    throws Exception
  {
    Object req = ((GenericRecord)request).get("req");
    JSONObject reqObj = JSON.parseObject(req.toString());
    JSONObject resObj = new JSONObject();
    String cardNo = reqObj.getString("cardNo");
    String openOper = reqObj.getString("openOper");
    if (StringUtils.isBlank(cardNo))
    {
      resObj.put("isSuccess", Integer.valueOf(1));
      resObj.put("errorCode", DzErrorCode.CardErrorCode.CARD_NO_IS_NULL.value());
      resObj.put("errorMsg", DzErrorCode.CardErrorCode.CARD_NO_IS_NULL.getDesc());
      return resObj.toJSONString();
    }
    if (StringUtils.isBlank(openOper)) {
      openOper = "system";
    }
    OfflineAccountVO offlineCount = new OfflineAccountVO();
    offlineCount.setCardNo(cardNo);
    offlineCount.setOpenOper(openOper);
    offlineCount.setOpenDate(DateUtil.getDBCurrentTime());
    offlineCount.setState(DzConstants.cardState.ACTIVATE.value());
    try
    {
      if (this.offlineAccountService.activateCard(offlineCount))
      {
        resObj.put("isSuccess", Integer.valueOf(1));
        resObj.put("errorMsg", "ok");
        return resObj.toJSONString();
      }
      resObj.put("isSuccess", Integer.valueOf(0));
      resObj.put("errorCode", DzErrorCode.CardErrorCode.NOT_FOUND.value());
      resObj.put("errorMsg", DzErrorCode.CardErrorCode.NOT_FOUND.getDesc() + "，卡号：" + cardNo);
      return resObj.toJSONString();
    }
    catch (Exception e)
    {
      LogUtil.error("激活离线卡异常，参数位：" + req.toString());
      throw e;
    }
  }
  
  public Object queryOfflineCard(Object request)
    throws Exception
  {
    JSONObject resObj = new JSONObject();
    try
    {
      Object req = ((GenericRecord)request).get("req");
      JSONObject reqObj = JSON.parseObject(req.toString());
      String cardNo = reqObj.getString("cardNo");
      if (StringUtils.isBlank(cardNo))
      {
        resObj.put("isSuccess", Integer.valueOf(0));
        resObj.put("errorCode", DzErrorCode.CardErrorCode.CARD_NO_IS_NULL.value());
        resObj.put("errorMsg", DzErrorCode.CardErrorCode.CARD_NO_IS_NULL.getDesc());
        return resObj.toJSONString();
      }
      OfflineAccountVO offlineAccout = new OfflineAccountVO();
      offlineAccout.setCardNo(cardNo);
      List<OfflineAccountVO> offlineList = this.offlineAccountService.queryOfflineAccount(offlineAccout);
      if (CollectionUtils.isEmpty(offlineList))
      {
        resObj.put("isSuccess", Integer.valueOf(0));
        resObj.put("errorCode", DzErrorCode.CardErrorCode.NOT_FOUND.value());
        resObj.put("errorMsg", DzErrorCode.CardErrorCode.NOT_FOUND.getDesc());
        return resObj.toJSONString();
      }
      OfflineAccountVO tmp = (OfflineAccountVO)offlineList.get(0);
      resObj.put("isSuccess", Integer.valueOf(1));
      resObj.put("cardState", tmp.getState());
      resObj.put("acctBal", tmp.getAcctBal());
      return resObj.toJSONString();
    }
    catch (Exception e)
    {
      LogUtil.error("查询离线卡异常，参数为：");
      throw e;
    }
  }
  
  public Object recharge(Object request)
    throws Exception
  {
    JSONObject resultJson = new JSONObject();
    try
    {
      Object req = ((GenericRecord)request).get("req");
      String tradeReq = req.toString();
      TranInfoVO tranInfoVO = (TranInfoVO)JSONObject.parseObject(tradeReq, TranInfoVO.class);
      if (StringUtils.isBlank(tranInfoVO.getServiceNo())) {
        tranInfoVO.setServiceNo(this.rechargeServiceNo);
      }
      if ((tranInfoVO.getServiceNo() == null) || (tranInfoVO.getPaymentAmount() == null) || 
        (tranInfoVO.getPayTypeCode() == null) || (tranInfoVO.getPayStateCode() == null) || 
        (null == tranInfoVO.getCardNo()) || (StringUtils.isBlank(tranInfoVO.getAppId())) || 
        (StringUtils.isBlank(tranInfoVO.getChannelCode())))
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.CommonErrorCode.PARAM_REQUIRED.getDesc());
        resultJson.put("errorCode", DzErrorCode.CommonErrorCode.PARAM_REQUIRED.value());
        return resultJson.toJSONString();
      }
      if (BigDecimalUtil.compareTo(new BigDecimal("0"), tranInfoVO.getPaymentAmount()) >= 0)
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.CardErrorCode.CASH_MUST_GREATER_THAN_ZERO.getDesc());
        resultJson.put("errorCode", DzErrorCode.CardErrorCode.CASH_MUST_GREATER_THAN_ZERO.value());
        return resultJson.toJSONString();
      }
      if (StringUtils.isBlank(tranInfoVO.getCardType())) {
        tranInfoVO.setCardType(this.cardTypeServiceImpl.getCardType(tranInfoVO.getCardNo()));
      }
      if (!DzConstants.payState.PAY_SUCCESS.value().equals(tranInfoVO.getPayStateCode()))
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.TranErrorCode.PAY_STATE_ERROR.getDesc());
        resultJson.put("errorCode", DzErrorCode.TranErrorCode.PAY_STATE_ERROR.value());
        return resultJson.toJSONString();
      }
      OrderServiceVO serviceVO = this.orderService.queryServiceByCode(tranInfoVO.getServiceNo());
      if (null == serviceVO)
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.TranErrorCode.SERVICE_NOT_FOUND
          .getDesc() + ",服务编码为：" + tranInfoVO.getServiceNo());
        resultJson.put("errorCode", DzErrorCode.TranErrorCode.SERVICE_NOT_FOUND.value());
        return resultJson.toJSONString();
      }
      if (tranInfoVO.getAppId().length() > 3)
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.CommonErrorCode.PARAM_TOO_LARGE.getDesc() + ",appId只能3位。");
        resultJson.put("errorCode", DzErrorCode.CommonErrorCode.PARAM_TOO_LARGE.value());
        return resultJson.toJSONString();
      }
      if (StringUtils.isBlank(tranInfoVO.getReceiver()))
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.MerchErrorCode.MERCHANT_IS_REQUIRED.getDesc());
        resultJson.put("errorCode", DzErrorCode.MerchErrorCode.MERCHANT_IS_REQUIRED.value());
        return resultJson.toJSONString();
      }
      MerchantVO mv = this.merchantDAO.queryMerchantByCode(tranInfoVO.getReceiver());
      if (null == mv)
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.MerchErrorCode.NOT_FOUND.getDesc());
        resultJson.put("errorCode", DzErrorCode.MerchErrorCode.NOT_FOUND.value());
        return resultJson.toJSONString();
      }
      tranInfoVO.setAccountState(DzConstants.accountingState.WAIT_FOR_ACCOUNTING.value());
      tranInfoVO.setPlatTime(DateUtil.getDBCurrentTime());
      tranInfoVO.setAccountingDate(this.commonService.getAccountingDate());
      tranInfoVO.setOriginalPayer(tranInfoVO.getCardNo());
      tranInfoVO.setOriginalPayerType(DzConstants.userType.OFFLINE_CUSTOMER.value());
      tranInfoVO.setPayer(tranInfoVO.getCardNo());
      tranInfoVO.setPayerType(DzConstants.userType.OFFLINE_CUSTOMER.value());
      tranInfoVO.setReceiverType(DzConstants.userType.MERCHANT_CUSTOMER.value());
      tranInfoVO.setReceiverName(mv.getShortName());
      String currentDate = DateUtil.getDateFormatter();
      String seqNo = DZStringUtil.getFixedLengthString(8, 
        String.valueOf(this.tradeDAO.querySequence("seq_trade_no")));
      String tradNo = String.valueOf(DzConstants.userType.OFFLINE_CUSTOMER.value()) + tranInfoVO.getAppId() + currentDate + seqNo;
      

      tranInfoVO.setTradeNo(tradNo);
      int n = this.tradeDAO.insertTranInfo(tranInfoVO);
      if (n == 0) {
        throw new BusinessException(DzErrorCode.TranErrorCode.SAVE_TRAN_INFO_FAIL.value(), DzErrorCode.TranErrorCode.SAVE_TRAN_INFO_FAIL.getDesc(), DzErrorCode.TranErrorCode.SAVE_TRAN_INFO_FAIL.getDesc());
      }
      OfflineAccountVO offlineAccount = new OfflineAccountVO();
      offlineAccount.setCardNo(tranInfoVO.getCardNo());
      offlineAccount.setAcctBal(tranInfoVO.getPaymentAmount());
      offlineAccount.setLastDate(DateUtil.getDBCurrentTime());
      if (!this.offlineAccountService.updatetOfflineAccountBal(offlineAccount)) {
        throw new BusinessException(DzErrorCode.ExceptionErrorCode.COMMON_EXCEPTION.value(), DzErrorCode.ExceptionErrorCode.COMMON_EXCEPTION.getDesc(), DzErrorCode.ExceptionErrorCode.COMMON_EXCEPTION.getDesc());
      }
      resultJson.put("isSuccess", Integer.valueOf(1));
      return resultJson.toJSONString();
    }
    catch (Exception e)
    {
      LogUtil.error("离线卡充值异常，参数为：" + request.toString());
      throw e;
    }
  }
  
  public Object cancelOfflineCard(Object request)
    throws Exception
  {
    JSONObject resultJson = new JSONObject();
    try
    {
      Object req = ((GenericRecord)request).get("req");
      String tradeReq = req.toString();
      TranInfoVO tranInfoVO = (TranInfoVO)JSONObject.parseObject(tradeReq, TranInfoVO.class);
      tranInfoVO.setServiceNo(this.cancelOfflineCardServiceNo);
      if ((tranInfoVO.getServiceNo() == null) || (tranInfoVO.getPaymentAmount() == null) || 
        (tranInfoVO.getPayTypeCode() == null) || (tranInfoVO.getPayStateCode() == null) || 
        (null == tranInfoVO.getCardNo()) || (null == tranInfoVO.getCardType()) || (StringUtils.isBlank(tranInfoVO.getPayer())) || 
        (StringUtils.isBlank(tranInfoVO.getAppId())) || (StringUtils.isBlank(tranInfoVO.getChannelCode())))
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.CommonErrorCode.PARAM_REQUIRED.getDesc());
        resultJson.put("errorCode", DzErrorCode.CommonErrorCode.PARAM_REQUIRED.value());
        return resultJson.toJSONString();
      }
      OrderServiceVO serviceVO = this.orderService.queryServiceByCode(tranInfoVO.getServiceNo());
      if (null == serviceVO)
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.TranErrorCode.SERVICE_NOT_FOUND
          .getDesc() + ",服务编码为：" + tranInfoVO.getServiceNo());
        resultJson.put("errorCode", DzErrorCode.TranErrorCode.SERVICE_NOT_FOUND.value());
        return resultJson.toJSONString();
      }
      if (BigDecimalUtil.compareTo(new BigDecimal("0"), tranInfoVO.getPaymentAmount()) >= 0)
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.CardErrorCode.CASH_MUST_GREATER_THAN_ZERO.getDesc());
        resultJson.put("errorCode", DzErrorCode.CardErrorCode.CASH_MUST_GREATER_THAN_ZERO.value());
        return resultJson.toJSONString();
      }
      if (tranInfoVO.getAppId().length() > 3)
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.CommonErrorCode.PARAM_TOO_LARGE.getDesc() + ",appId只能3位。");
        resultJson.put("errorCode", DzErrorCode.CommonErrorCode.PARAM_TOO_LARGE.value());
        return resultJson.toJSONString();
      }
      if ((!DzConstants.PayType.THIRD_REALTIME_PAY.value().equals(tranInfoVO.getPayTypeCode())) && 
        (!DzConstants.PayType.CASH_PAY.value().equals(tranInfoVO.getPayTypeCode())))
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.TranErrorCode.PAYTYPE_NOTMATCH_TRADETYPE.getDesc() + ";退卡业务只支持现金支付和第三方实时支付。");
        resultJson.put("errorCode", DzErrorCode.TranErrorCode.PAYTYPE_NOTMATCH_TRADETYPE.value());
        return resultJson.toJSONString();
      }
      if ((DzConstants.PayType.THIRD_REALTIME_PAY.value().equals(tranInfoVO.getPayTypeCode())) && (
        (StringUtils.isBlank(tranInfoVO.getChannelCode())) || 
        (StringUtils.isBlank(tranInfoVO.getThdPaySeq())) || (null == tranInfoVO.getThdEndTime())))
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.CommonErrorCode.PARAM_REQUIRED.getDesc());
        resultJson.put("errorCode", DzErrorCode.CommonErrorCode.PARAM_REQUIRED.value());
        return resultJson.toJSONString();
      }
      MerchantVO mv = this.merchantDAO.queryMerchantByCode(tranInfoVO.getPayer());
      if (null == mv)
      {
        resultJson.put("isSuccess", Integer.valueOf(0));
        resultJson.put("errorMsg", DzErrorCode.MerchErrorCode.NOT_FOUND.getDesc());
        resultJson.put("errorCode", DzErrorCode.MerchErrorCode.NOT_FOUND.value());
        return resultJson.toJSONString();
      }
      tranInfoVO.setAccountState(DzConstants.accountingState.WAIT_FOR_ACCOUNTING.value());
      tranInfoVO.setPlatTime(DateUtil.getDBCurrentTime());
      tranInfoVO.setAccountingDate(this.commonService.getAccountingDate());
      tranInfoVO.setOriginalPayer(tranInfoVO.getPayer());
      tranInfoVO.setOriginalPayerType(DzConstants.userType.MERCHANT_CUSTOMER.value());
      tranInfoVO.setPayerType(DzConstants.userType.MERCHANT_CUSTOMER.value());
      tranInfoVO.setReceiverType(DzConstants.userType.OFFLINE_CUSTOMER.value());
      tranInfoVO.setReceiver(tranInfoVO.getCardNo());
      tranInfoVO.setPayerName(mv.getShortName());
      String currentDate = DateUtil.getDateFormatter();
      String seqNo = DZStringUtil.getFixedLengthString(8, 
        String.valueOf(this.tradeDAO.querySequence("seq_trade_no")));
      String tradNo = String.valueOf(DzConstants.userType.OFFLINE_CUSTOMER.value()) + tranInfoVO.getAppId() + currentDate + seqNo;
      

      tranInfoVO.setTradeNo(tradNo);
      int n = this.tradeDAO.insertTranInfo(tranInfoVO);
      if (n == 0) {
        throw new BusinessException(DzErrorCode.TranErrorCode.SAVE_TRAN_INFO_FAIL.value(), DzErrorCode.TranErrorCode.SAVE_TRAN_INFO_FAIL.getDesc(), DzErrorCode.TranErrorCode.SAVE_TRAN_INFO_FAIL.getDesc());
      }
      OfflineAccountVO offlineAccount = new OfflineAccountVO();
      offlineAccount.setCardNo(tranInfoVO.getCardNo());
      offlineAccount.setAcctBal(BigDecimalUtil.sub(BigDecimal.valueOf(0L), tranInfoVO.getPaymentAmount()));
      offlineAccount.setLastDate(DateUtil.getDBCurrentTime());
      if (!this.offlineAccountService.updatetOfflineAccountBal(offlineAccount)) {
        throw new BusinessException(DzErrorCode.ExceptionErrorCode.COMMON_EXCEPTION.value(), DzErrorCode.ExceptionErrorCode.COMMON_EXCEPTION.getDesc(), DzErrorCode.ExceptionErrorCode.COMMON_EXCEPTION.getDesc());
      }
      resultJson.put("isSuccess", Integer.valueOf(1));
      return resultJson.toJSONString();
    }
    catch (Exception e)
    {
      LogUtil.error("离线卡充值异常，参数为：" + request.toString());
      throw e;
    }
  }
}
